package cn.klaw.properties;



import lombok.Data;

import java.util.Collections;
import java.util.List;

/**
 * mvc配置
 *
 * @version V5.0.0
 *
 * @date 2025/1/16 8:47
 */
@Data
public class MvcSecurityProperties {

    public static final String PREFIX = "spring.mvc";

    public static final String HEADER_XFRAME_OPTIONS = "X-Frame-Options";
    public static final String HEADER_XSS_PROTECTION = "X-XSS-Protection";
    public static final String HEADER_Content_Type_Options = "X-Content-Type-Options";

    /**
     * 默认配置 Content-Security-Policy
     * 只允许请求同源、内联、动态脚本
     * <a href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Security-Policy">参考文章</a>
     */
    private static final String DEFAULT_CONTENT_SECURITY_POLICY = "default-src  'self' 'unsafe-eval' 'unsafe-inline';font-src 'self' data: blob; img-src 'self' data: blob:;frame-ancestors 'self';script-src 'self' 'unsafe-eval' 'unsafe-inline' https://cdn.staticfile.org;";


    /**
     * 跨域相关配置
     * 默认允许全部域名跨域
     */
    private Cors cors = new Cors();

    /**
     * 头部相关配置
     */
    private Headers headers = new Headers();

    /**
     * CSRF防御, 验证放空不验证, 填写允许的域名
     */
    private List<String> csrfOrigins = Collections.emptyList();;

    /**
     * CSRF防御, 放空不验证, 填写允许的域名正则
     */
    private List<String> csrfOriginsPatterns = Collections.emptyList();;


    @Data
    public static class Headers{

        /**
         * 返回的Web服务器名称
         */
        private String serverName;

        /**
         * XSS保护
         * 0 :禁用; 1 :启用; 1;mode=block :启用, 如果检测到攻击停止渲染
         */
        private XXssProtectionMode xXssProtection = XXssProtectionMode.ENABLED_MODE_BLOCK;

        /**
         * 是否允许在Iframe中被加载
         * deny :不允许; sameorign :允许相同的域名; allow-from-uri 域名:允许指定来源
         */
        private XFrameOptionsMode xFrameOptions = XFrameOptionsMode.SAMEORIGIN;

        /**
         * MIME嗅探
         * nosniff
         */
        private XContentTypeOptions xContentTypeOptions = XContentTypeOptions.DISABLED;
    }

    @Data
    public static class Cors{


        private static final String ALL = "*";
        private static final String ALL_PATTERNS = "**";
        private static final Long MAX_AGE = 18000L;

        /**
         * 允许跨域的域名
         */
        private List<String> allowedOrigins = Collections.emptyList();
        /**
         * 允许跨域的域名正则匹配
         */
        private List<String> allowedOriginPatterns = Collections.singletonList(ALL_PATTERNS);
        /**
         * 允许跨域的请求方法
         */
        private List<String> allowedMethods = Collections.singletonList(ALL);
        /**
         * 允许跨域的头部信息
         */
        private List<String> allowedHeaders = Collections.singletonList(ALL);
        /**
         * 预检请求的有效期, 单位为秒
         */
        private long optionsMaxAge = MAX_AGE;

    }



    public enum XContentTypeOptions {

        /**
         * 不处理
         */
        DISABLED("disabled"),

        /**
         * 不允许浏览器嗅探资源类型
         */
        NOSNIFF("nosniff");

        private final String mode;

        XContentTypeOptions(String mode) {
            this.mode = mode;
        }

        public String getMode() {
            return this.mode;
        }

    }

    public enum XFrameOptionsMode {

        /**
         * 不处理
         */
        DISABLED("disabled"),

        /**
         * 不允许在iframe中被加载
         */
        DENY("deny"),

        /**
         *  允许在相同的域名的iframe中被加载
         */
        SAMEORIGIN("sameorigin");

        private final String mode;

        XFrameOptionsMode(String mode) {
            this.mode = mode;
        }

        public String getMode() {
            return this.mode;
        }

    }


    public enum XXssProtectionMode {

        /**
         * 禁用; ;
         */
        DISABLED("0"),

        /**
         * 启用
         */
        ENABLED("1"),

        /**
         * 启用, 如果检测到攻击停止渲染
         */
        ENABLED_MODE_BLOCK("1; mode=block");

        private final String mode;

        XXssProtectionMode(String mode) {
            this.mode = mode;
        }

        public String getMode() {
            return this.mode;
        }

    }
}
